#ifndef _gdt_idt_h
#define _gdt_idt_h

/* sekiOS
 *
 * desctabl.h - IDT and GDT fluff
 */

/* Defines a GDT entry. We say packed, because it prevents the
*  compiler from doing things that it thinks is best: Prevent
*  compiler "optimization" by packing */
struct gdt_entry
{
  unsigned short limit_low;
  unsigned short base_low;
  unsigned char base_middle;
  unsigned char access;
  unsigned char granularity;
  unsigned char base_high;
} __attribute__ ((packed));

struct gdt_ptr
{
  unsigned short limit;
  unsigned int base;
} __attribute__ ((packed));

// omfg
// [02:55] <+sekio> its a big problem if your GDT CANT FUCKING FIT THE TSS
struct gdt_entry gdt[15];
struct gdt_ptr gdtp;

extern void gdt_flush ();
extern void gdt_install ();
extern void gdt_set_gate (int num, unsigned long base, unsigned long limit,
                          unsigned char access, unsigned char gran);



/* IDT stuff */

/* Defines an IDT entry */
struct idt_entry
{
  unsigned short base_lo;
  unsigned short sel;
  unsigned char always0;
  unsigned char flags;
  unsigned short base_hi;
} __attribute__ ((packed));

struct idt_ptr
{
  unsigned short limit;
  unsigned int base;
} __attribute__ ((packed));

struct idt_entry idt[256]; // our idt
struct idt_ptr idtp;

extern void idt_install ();
extern void idt_load ();
extern void idt_set_gate (unsigned char num, unsigned long base,
                          unsigned short sel, unsigned char flags);


/* TSS stuff */

typedef struct TAGtss_entry_t
{
   unsigned int prev_tss;   // The previous TSS - if we used hardware task switching this would form a linked list.
   unsigned int esp0;       // The stack pointer to load when we change to kernel mode.
   unsigned int ss0;        // The stack segment to load when we change to kernel mode.
   unsigned int esp1;       // Unused...
   unsigned int ss1;
   unsigned int esp2;
   unsigned int ss2;
   unsigned int cr3;
   unsigned int eip;
   unsigned int eflags;
   unsigned int eax;
   unsigned int ecx;
   unsigned int edx;
   unsigned int ebx;
   unsigned int esp;
   unsigned int ebp;
   unsigned int esi;
   unsigned int edi;
   unsigned int es;         // The value to load into ES when we change to kernel mode.
   unsigned int cs;         // The value to load into CS when we change to kernel mode.
   unsigned int ss;         // The value to load into SS when we change to kernel mode.
   unsigned int ds;         // The value to load into DS when we change to kernel mode.
   unsigned int fs;         // The value to load into FS when we change to kernel mode.
   unsigned int gs;         // The value to load into GS when we change to kernel mode.
   unsigned int ldt;        // Unused...
   unsigned short trap;
   unsigned short iomap_base;
} __attribute__((packed)) tss_entry_t;

tss_entry_t tss_entry;

extern void tss_flush();
extern void tss_set_stack(unsigned int);


#endif

